package com.study.juc;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;

public interface BlockQueue<T> {
    
    boolean offer(T element) ;
    
    T take();
    
    int getMaxSize();
    
    
    
    
}

class MyBlockQueue<T> implements BlockQueue<T>{

    
    
    private final LinkedList<T>  queue =new LinkedList<>();
    private final int maxSize;
    
    private int length;
    private static final int DEFAULT_MAX_SIZE = 20;

    public MyBlockQueue() {
        this(DEFAULT_MAX_SIZE);
    }
    public MyBlockQueue(int maxSize) {
        this.maxSize = maxSize;
    }

    @Override
    public boolean offer(T element) {
        synchronized (queue) {
            while (queue.size() > maxSize) {
                try {
                    //System.out.println("队列已满,等待中...");
                    queue.wait();
                } catch (Exception e) {
                    System.out.println("队列已满,当前被打断");
                }
            }
            queue.addLast(element);
            length++;
            queue.notifyAll();
        }
        return true;
    }

    @Override
    public T take() {
        synchronized (queue){
            while(queue.size() <= 0){
                try {
                    //System.out.println("队列已空,等待中...");
                    queue.wait();
                } catch (InterruptedException e) {
                }
            }
            T t = queue.removeFirst();
            length--;
            queue.notifyAll();
            return t;
        }
    }

    @Override
    public int getMaxSize() {
        synchronized (queue){
            return length;
        }
    }

    public static void main(String[] args) {

        BlockQueue<String> stringBlockQueue = new MyBlockQueue<String>(5);
        IntStream.range(0,20).forEach(a->{
            new Thread(()->{
                stringBlockQueue.offer(String.format("第%s个任务",a));
                System.out.println(Thread.currentThread().getName()+"放入:"+a);
            }).start();
        });

        IntStream.range(0,3).forEach(a->{
            new Thread(()->{
                String task;
                while( (task = stringBlockQueue.take()) !=null){
                    try {
                        TimeUnit.SECONDS.sleep(1L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"计算得到结果:"+task); 
                }

            }).start();
        });
        
    }
}
